1-2 荍Oうp氻kG{p刉

前一節所介紹的計時方法只是一個直接有效的方法,但只能對一段程式碼進行計時。本節將介紹 MATLAB 的「程式計時器」(Profiler,簡稱計時器),它可以分別計算每一個指令所佔用的執行時間,並列出詳細的統計表。尤其當你的函式又呼叫了其他函式,在如此一層包一層的情況下,唯有使用 MATLAB 計時器才能有效地計算出每一個函式所花的時間,並進而進行改進,可能的改進方向是:

如果你的視窗作業系統使用了 Intel 多核心晶片,為了使計時器能夠達到最穩定的結果,你必須先指定 MATLAB 只能使用一個核心,方法如下:
  1. 按下 Ctrl-Alt-Delete 以啟動工作管理員。
  2. 點選「處理程序」分頁。
  3. 以右鍵點選 MATLAB.exe,並選擇「設定親和性(A)...」。
  4. 只點選「CPU 0」,使 MATLAB.exe 只能在此核心上執行。
如果你是使用 Linux/Unix 作業系統,可以使用命令列來指定 MATLAB 只能使用一個核心,方法如下:
  1. 先使用下列指令找出 MATLAB 所對應的程序編號(Process ID, or PID):
    ps -C MATLAB
  2. 假設 PID 是 8674,則我們可以使用下列指令來查詢 MATLAB 可以使用的核心:
    taskset -pc 8674
  3. 最後,我們可以設定 MATLAB 只用一個核心:
    taskset -pc 0 8674
(當你使用完 MATLAB 計時器後,記得將這些設定改回原先的設定。)

MATLAB 計時器的指令是 profile,在其後可加上不同的選項,以代表不同功能。例如,若要對 for 迴圈及所用到的指令分別計時,可以參考下列範例:

Example 1: 01-程式計時/profile01.mprofile on % 啟動計時器 for i = 1:1000 a = inv(rand(100)); % 計算 100x100 亂數矩陣的反矩陣 b = mean(rand(100)); % 計算 100x100 亂數矩陣的每一直行平均值 end profile viewer % 呈現計時結果

執行完上述程式碼後,MATLAB 會將執行所花費時間的統計資料顯示出來,如下圖:

由上圖可得知,mean 指令共被呼叫了 1000 次 ,佔用的 Total Time 是 0.038 秒(包含在 mean 內部所有呼叫其他函式的時間),而 Self Time 只有 0.022 秒,此時間並不包含 mean 函式(在此為 M 檔案)內部呼叫其他函式所花的時間。此外,inv 和 rand 各被呼叫 1000 和 2000 次,因為這兩個指令都是都是內建指令,因此他們的 Total Time 會等於 Self Time,所花的時間都可以由上表一目瞭然。

Hint
欲知一指令是內建指令或是 M 檔案,用 which 指令檢視其來源即可。讀者可輸入 which mean 及 which inv,看看傳回訊息之不同處。

若要知道 mean 函式的內部計時情況,可以點選上述視窗的 “mean” 連結,結果如下:

由上圖可以得到 mean 函式的內部計時結果,我們甚至可以看到最花時間的敘述出現在第 28 列,根據這些訊息,我們就可以使用「擒賊擒王」的原則來對此列進行最佳化,以求整體計算速度的提昇。在上圖列表,亦包含了所有內建指令的計時資料。此時若再點選任一個函式連結,就可以更清楚地看出每一個指令的 parent 指令(即呼叫此指令的上層指令)和 children 指令(即被此指令所呼叫的下層指令),以及他們各自所佔用的時間。

在上述範例中,MATLAB 計時器在預設的情況下,是對所有的函式進行計時,這些函式包含 M 檔案、MEX 檔案,以及內建指令。但通常內建指令已經是最佳化的狀態,通常不太可能去加速,我們可以改變計時器,只針對 M 檔案及 MEX 檔案進行計時,因為這兩種檔案才比較有改善的空間。欲使 profile 指令只對 M 檔案及 MEX 檔案進行計時,可在 profile on 之後接上「-detail mmex」,例如:

Example 2: 01-程式計時/profile02.mprofile on -detail mmex % 啟動計時器,對 M/MEX 檔案計時 for i = 1:1000 a = inv(rand(100)); % 計算 100x100 亂數矩陣的反矩陣 b = mean(rand(100)); % 計算 100x100 亂數矩陣的每一直行平均值 end profile viewer % 呈現計時結果

此時計時結果將只有包含 M 檔案及 MEX 檔案,如下圖:

由於我們只在意 M 檔案(這裡只有 mean 指令)和 MEX 檔案(在這裡並未出現)的執行時間,所以整個報表變得相當簡單。我們仍然可以點選上述視窗的 “mean” 連結,就可以看到此函式內部執行所花的時間。

Hint
  • profile -detail builtin: 對所有函式(含 M/MEX 檔案、內建指令)計時,此為預設值
  • profile -detail mmex: 只對 M/MEX 檔案計時


MATLAB程式設計:進階篇